/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package UserInterface.AnnotationCompare;

import ResultEditor.Annotations.Depot;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;

/**
 *
 * @author leng 2010-11-09 1153am
 */
public class ExpandButton extends JPanel{

    /**it's true only if main annotation is loaded and displayed on the editor
     * panel.*/
    private boolean isCompare=false;

    /** predefine colors to draw the button later*/
    //private Color   out = new Color(189, 189, 189 );
    //private Color  line = new Color( 51,  51,  51 );
    //private Color inner = new Color(128, 128, 128 );
    protected JSplitPane js, jsParent;
    protected JPanel panel_container;
    protected JButton jbutton_spaneditor_delete;
    protected JLabel jSeperator;
    // components imported for controlling
    protected JToolBar toolbar_comparision_buttons;
    protected UserInterface.GUI gui;
    protected JList jList1;
    protected JTextPane textPaneforClinicalNotes;

    private UserInterface.AnnotationCompare.Comparator compartor;


    /**Return boolean value to indicate the comparator panel has been expanded
     * or not.
     *
     * @return  true, if the comparator has been expanded;
     *          false, otherwise.
     */
    public boolean isComparatorPanelExpanded(){
        if((statu == status.button_canbehide)||(statu == status.button_canbehide))
            return true;
        else
            return false;
    }

    /**constructor*/
    public ExpandButton(JSplitPane js, JSplitPane jsParent, JPanel panel_container){
        // call super
        super();
        this.js = js;
        this.jsParent = jsParent;
        this.panel_container = panel_container;

        

        // set additional component attributes
        setComponent();
    }


    /**somehow, java could not send the panel_container ontime in the
     * constructor. So here we need to assign this container manually.
     * This function only need to be called after components got initilized in
     * class of GUI.
     *
     */
    public void setContainerPart(JPanel panel_container,
            JButton jbutton_spaneditor_delete,
            JLabel jSeperator,
            JToolBar toolbar_comparision_buttons,
            JList jList1,
            UserInterface.GUI gui,
            JTextPane textPaneforClinicalNotes
            ){
        this.panel_container = panel_container;
        this.jbutton_spaneditor_delete = jbutton_spaneditor_delete;
        this.jSeperator = jSeperator;
        this.toolbar_comparision_buttons = toolbar_comparision_buttons;
        this.jList1 = jList1;
        this.gui = gui;
        this.textPaneforClinicalNotes = textPaneforClinicalNotes;
    }


    public void setStatusInvisiable(){
        try{
            isCompare = false;

            this.setCursor( Cursor.getDefaultCursor() );
            this.js.setResizeWeight(1.0);

            this.hideRightPane();
            this.statu = status.button_invisiable;

            this.setToolbar_forNormal();

        }catch(Exception ex){
        }
        
        this.updateUI();
    }

    private void setToolbar_forCompare(){
        this.setVisible(true);
        try{
            jbutton_spaneditor_delete.setVisible(false);
            jSeperator.setVisible(false);
            toolbar_comparision_buttons.setVisible(true);
            gui.display_DisabledEditorModification_forCompareMode();

        }catch(Exception ex){
        }
    }

    /**User clicked button of "accept" on editor panel in comparation
     * mode to only accept primary annotation in this annotation set.
     */
    public void acceptreject_acceptPrimaryAnnotation(){

        // user click accept button on editor panel
        try{// ##1## delete
            Depot.SelectedAnnotationSet.data_onlyKeepPrimaryAnnotation();

            // ##2## remove components on comparator panel
            this.setStatusInvisiable();
            

            // ##3## show primary annotation on editor panel (annotation on list
            // and details on other fileds)
            gui.display_showSelectedAnnotations_inListOnEditorPanel(-1);
            gui.repaintHighlighter();
        }catch(Exception ex){
            System.out.println("error 1011171324:: fail to accept primiary " +
                    "annotation on editor panel" + ex.toString());
        }
        
    }


    /**User clicked button of "accept" on comparator panel in comparation
     * mode to only accept a specific annotation in this annotation set.
     *
     * @param   uniqueindex
     *          The unique index you want to accept in the annotation set.
     */
    public void acceptreject_acceptAlternativeAnnotation(int uniqueindex){

        // user click accept button on editor panel
        try{// ##1## delete
            Depot.SelectedAnnotationSet.data_onlyKeepAnnotation(uniqueindex);

            // ##2## remove components on comparator panel
            this.setStatusInvisiable();


            // ##3## show primary annotation on editor panel (annotation on list
            // and details on other fileds)
            gui.display_showSelectedAnnotations_inListOnEditorPanel(-1);
            gui.repaintHighlighter();
        }catch(Exception ex){
            System.out.println("error 1011171324:: fail to accept primiary " +
                    "annotation on editor panel" + ex.toString());
        }

    }


    /**User clicked button of "reject" on editor panel in comparation
     * mode to select next annotation in this annotation set as primary
     * annotation.
     */
    public void acceptreject_rejectPrimaryAnnotation(){
        
        try{
            //##1## delete primary annotation
            Depot.SelectedAnnotationSet.data_onlyDeletePrimaryAnnotation();

            // ##2## if there only have 2 annotations in current selected
            // annotation set
            if( Depot.SelectedAnnotationSet.size()==1){

                // ##2.1## remove components on comparator panel
                this.setStatusInvisiable();
                
                // ##2.2## show primary annotation on editor panel (annotation
                // on list and details on other fileds)
                gui.display_showSelectedAnnotations_inListOnEditorPanel(-1);
                gui.repaintHighlighter();

            }else{
                // ##3## find first one annotation in rest annotations and show
                // it on
                int uniqueindex = Depot.SelectedAnnotationSet.getSelectedAnnotationSet().get( 0 );
                Depot.SelectedAnnotationSet.ui_objectAnnotation = uniqueindex;
                gui.display_showOneAnnotation_inListOnEditorPanel( uniqueindex );                
                isCompare = true;

                this.display_showAnnotations_inComparatorList();
                
                gui.repaintHighlighter();
            }

        }catch(Exception ex){
            System.out.println("error 1011171325:: fail to reject primiary " +
                    "annotation on editor panel" + ex.toString());
        }
    }


    /**Sometimes, these is one or more annotation(s) appreared in the
     * annotations set which you selected for compare. But these annotations
     * do not belong this set. We click the "ignore" button in comparasion
     * mode to kick this/these annotation(s) out of our annotation set and
     * then we can continue our accept/reject operation to solve our
     * conflicts.
     */
    public void acceptreject_ignorePrimaryAnnotation(){
        try{
            //##1## delete primary annotation
            Depot.SelectedAnnotationSet.data_onlyIgnorePrimaryAnnotation();

            // ##2## if there only have 2 annotations in current selected
            // annotation set
            if( Depot.SelectedAnnotationSet.size()==1){

                // ##2.1## remove components on comparator panel
                this.setStatusInvisiable();

                // ##2.2## show primary annotation on editor panel (annotation
                // on list and details on other fileds)
                gui.display_showSelectedAnnotations_inListOnEditorPanel(-1);
                gui.repaintHighlighter();

            }else{
                // ##3## find first one annotation in rest annotations and show
                // it on
                int uniqueindex = Depot.SelectedAnnotationSet.getSelectedAnnotationSet().get( 0 );
                Depot.SelectedAnnotationSet.ui_objectAnnotation = uniqueindex;
                gui.display_showOneAnnotation_inListOnEditorPanel( uniqueindex );
                isCompare = true;

                this.display_showAnnotations_inComparatorList();

                gui.repaintHighlighter();
            }

        }catch(Exception ex){
            System.out.println("error 1011171325:: fail to reject primiary " +
                    "annotation on editor panel" + ex.toString());
        }
    }



    /**User clicked button of "reject" on comprator panel in comparation
     * mode to select next annotation in this annotation set as primary
     * annotation.
     *
     * @param   uniqueindex
     *          unique index of annotation which you want to reject from
     *          selected annotation set.
     */
    public void acceptreject_rejectAlternativeAnnotation(int uniqueindex){

        try{
            //##1## delete primary annotation
            Depot.SelectedAnnotationSet.data_onlyDeleteSpcificAnnotation(uniqueindex);

            // ##2## if there only have 2 annotations in current selected
            // annotation set
            if( Depot.SelectedAnnotationSet.size()==1){

                // ##2.1## remove components on comparator panel
                this.setStatusInvisiable();

                // ##2.2## show primary annotation on editor panel (annotation
                // on list and details on other fileds)
                gui.display_showSelectedAnnotations_inListOnEditorPanel(-1);
                gui.repaintHighlighter();

            }else{
                // ##3## find first one annotation in rest annotations and show
                // it on
                this.display_showAnnotations_inComparatorList();
                gui.repaintHighlighter();
            }

        }catch(Exception ex){
            System.out.println("error 1011171325:: fail to reject primiary " +
                    "annotation on editor panel" + ex.toString());
        }
    }



    /**User clicked button of "ignore" on comprator panel in comparation
     * mode to kick out one annotation from current set. This annotation
     * will be move out from current set but it still stay in the memory
     * of annotations depot.
     *
     * @param   uniqueindex
     *          unique index of annotation which you want to kick out from
     *          selected annotation set.
     */
    public void acceptreject_ignoreAlternativeAnnotation(int uniqueindex){

        try{
            //##1## delete primary annotation
            Depot.SelectedAnnotationSet.data_onlyIgnoreSpcificAnnotation(uniqueindex);

            // ##2## if there only have 2 annotations in current selected
            // annotation set
            if( Depot.SelectedAnnotationSet.size()==1){

                // ##2.1## remove components on comparator panel
                this.setStatusInvisiable();

                // ##2.2## show primary annotation on editor panel (annotation
                // on list and details on other fileds)
                gui.display_showSelectedAnnotations_inListOnEditorPanel(-1);
                gui.repaintHighlighter();

            }else{
                // ##3## find first one annotation in rest annotations and show
                // it on
                this.display_showAnnotations_inComparatorList();
                gui.repaintHighlighter();
            }

        }catch(Exception ex){
            System.out.println("error 1011221425:: fail to ignore selected " +
                    "annotation on compare panel" + ex.toString());
        }
    }




    private void setToolbar_forNormal(){
        try{
            isCompare = false;

            jbutton_spaneditor_delete.setVisible(true);
            jSeperator.setVisible(true);
            toolbar_comparision_buttons.setVisible(false);

            gui.display_removeRectangle_toPotensionMarkedDifferences();
            gui.display_EnabledEditorModification_forLeaveCompareMode();

        }catch(Exception ex){
        }
    }

    public void setStatusExpandable(){
        this.setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ));
        this.statu = status.button_canbeExpand;
        this.js.setResizeWeight(1.0);

        this.setToolbar_forNormal();

        this.updateUI();
    }

    private void setComponent(){

        this.statu = status.button_invisiable;

        // set component size
        int fixed_height = 28;
        int fixed_width = 45;
        this.setPreferredSize( new Dimension(fixed_width, fixed_height));
        //this.setBackground(Color.yellow);
        // set cursor style
        //this.setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) );


        this.addMouseListener( new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent me) {
                mouseClicked_OnButton();
            }

            @Override
            public void mousePressed(MouseEvent me) {
            }

            @Override
            public void mouseReleased( MouseEvent me ) {

            }

            @Override
            public void mouseEntered( MouseEvent me ) {
                if(ExpandButton.this.statu == status.button_canbeExpand){
                    ExpandButton.this.statu = status.button_canbeExpand_mouseon;
                    ExpandButton.this.updateUI();

                    return;

                }else if(ExpandButton.this.statu == status.button_canbehide){
                    ExpandButton.this.statu = status.button_canbehide_mouse;
                    ExpandButton.this.updateUI();

                    return;
                }
            }

            @Override
            public void mouseExited( MouseEvent me ) {
                if(ExpandButton.this.statu == status.button_canbeExpand_mouseon){
                    ExpandButton.this.statu = status.button_canbeExpand;
                    ExpandButton.this.updateUI();

                    return;
                } else if(ExpandButton.this.statu == status.button_canbehide_mouse){
                    ExpandButton.this.statu = status.button_canbehide;
                    ExpandButton.this.updateUI();

                    return;
                }

            }
        });

    }

    
    /**five status to this button*/
    public enum status{
        button_invisiable,  // default status to this button
        button_canbeExpand,
        button_canbeExpand_mouseon,
        button_canbehide,
        button_canbehide_mouse
    }

    
    private void mouseClicked_OnButton(){
        if((js==null)||(jsParent==null))
            return;

        // width of current right side part in this split pane
        int rightpane_size = js.getWidth() - js.getDividerSize();

        // Expand right pane on this split pane if allow you to expand the right
        // side of the split pane
        if((statu == status.button_canbeExpand)||(statu == status.button_canbeExpand_mouseon)){
            expandRightPane();
            display_showAnnotations_inEditor();
            display_showAnnotations_inComparatorList();
            return;
        }
        
        // hide right part
        if((statu == status.button_canbehide)||(statu == status.button_canbehide_mouse)){
            hideRightPane();
            showAnnotations_All_forExitCompare();
            statu = status.button_canbeExpand;

            return;
        }
    }

    /**show just one annotation on the main editor panel*/
    private void display_showAnnotations_inEditor(){
        if (gui==null)
            return;
        try{
            if(isCompare == false ){
                int uniqueindex = Depot.SelectedAnnotationSet.getSelectedAnnotationSet().get( jList1.getSelectedIndex() );
                Depot.SelectedAnnotationSet.ui_objectAnnotation = uniqueindex;
                
                gui.display_showOneAnnotation_inListOnEditorPanel( uniqueindex );
                
                //System.out.println("saved uid=" + Depot.SelectedAnnotationSet.ui_objectAnnotation);
                isCompare = true;
            }else{
                int uid = Depot.SelectedAnnotationSet.ui_objectAnnotation;
                gui.display_showOneAnnotation_inListOnEditorPanel( uid );

            }
        }catch(Exception ex){
        }
    }

    private void showAnnotations_All_forExitCompare(){
        if (gui==null)
            return;
        try{
            //System.out.println("forall uid=" + Depot.SelectedAnnotationSet.ui_objectAnnotation);
            gui.display_showSelectedAnnotations_inListOnEditorPanel( Depot.SelectedAnnotationSet.ui_objectAnnotation );

        }catch(Exception ex){
        }
    }


    private void expandRightPane(){

        this.setToolbar_forCompare();
        
        // This is the most suitable width of these two panes in their split
        // pane, if size less then it, eHOST shoult try to regain this size for
        // them.
        final int basewidth = 500;
        final int minibasewidth = 200;

        js.setDividerLocation( (int)(js.getWidth()/2));

        this.js.setResizeWeight(0.5);
        if(js.getWidth()<basewidth)
            jsParent.setDividerLocation( jsParent.getWidth() - basewidth );

        //  load jpane from class
        components_loadComparatorPane();

        statu = status.button_canbehide;
        this.updateUI();

    }

    /**Show all annotations except the primary annotation in the list
     * on comparator panel.
     */
    private void display_showAnnotations_inComparatorList(){
        try{
            if (this.compartor !=null){
                compartor.display_showAlternativeAnnotations();
            }
        }catch(Exception ex){
            System.out.println("error 10111423:: fail to show annotations in" +
                    "comparator panel\n" + ex.toString());
        }
    }

    private void components_loadComparatorPane(){
        if (panel_container == null)
            return;

        int comp_count = panel_container.getComponentCount();
        if( comp_count > 0 ){
            panel_container.removeAll();
        }
        try{
            //panel_container.add(new UserInterface.AnnotationCompare.Comparator() );
            compartor = new UserInterface.AnnotationCompare.Comparator(gui, this, textPaneforClinicalNotes);
            compartor.setOpaque(true);
            panel_container.setLayout(new BorderLayout());
            panel_container.add(compartor);
            panel_container.setVisible(true);

            //layout.
            panel_container.validate();
            panel_container.updateUI();
        } catch(Exception ex) {
            System.out.println("error 1011161419::fail to show" +
                    " component loads from form frame!!!\n" + ex.toString());
        }

    }

    private void hideRightPane(){
        try{
            this.setToolbar_forNormal();

            if(js==null)
                return;
            this.panel_container.removeAll();

            js.setDividerLocation( js.getWidth() );
            js.setResizeWeight(1.0);
        }catch(Exception ex){
            System.out.println("error 1011151502::"+ex.toString());
        }
    }



    
    public status statu;

 


    /**custom paint() method to this curstom component.*/
    @Override
    public void paint(Graphics g){
        super.paint(g);

        // ##1## draw nothing if button is invisiable
        if(statu == status.button_invisiable )
            return;


        int rules_height = 18;
        int rules_width  = 40;

        int this_width = this.getWidth(), this_height = this.getHeight();
        int start_x = ( this_width>rules_width ? ((int)(this_width-rules_width)) : 0);
        int start_y = ( this_height>rules_height? ((int)(this_height-rules_height)/2): 0 );
        int real_wholeWidth = ( this_width>rules_width ? rules_width-2: this_width-2);
        int real_wholeHeight = (this_height>rules_height? rules_height : this_height);
        int real_width = real_wholeWidth - (int)(real_wholeHeight/2);        

        // draw the outer rounder rectangle        
        // draw the outer rounder rectangle
        if ((statu == status.button_canbeExpand_mouseon)||(statu == status.button_canbehide_mouse))
            g.setColor(new Color(20,189,159));
        else
            g.setColor(new Color(2,89,159));


        // 填充渐进色
        int ir = g.getColor().getRed();
        int ig = g.getColor().getGreen();
        int ib = g.getColor().getBlue();
        int rr,gg,bb;

        for(int i=0; i<real_wholeHeight; i++){
            rr=ir+i*2;
            gg=ig+i*6;
            bb=ib+i*6;
            rr=(rr<255? rr:255);
            bb=(bb<255? bb:255);
            gg=(gg<255? gg:255);
            g.setColor(new Color(rr, gg, bb));
            int y = start_y + real_wholeHeight - 1 -i;
            if(i<=(int)(real_wholeHeight/2))
                g.drawLine(start_x + 1, y, start_x  + real_width + i, y );
            else
                g.drawLine(start_x + 1, y, start_x  + real_wholeWidth - (i-(int)(real_wholeHeight/2)), y );
        }

        // draw the outer rounder rectangle
        if ((statu == status.button_canbeExpand_mouseon)||(statu == status.button_canbehide_mouse))
            g.setColor(new Color(20,189,159));
        else
            g.setColor(new Color(2,89,159));
        g.drawLine(start_x, start_y, start_x + real_width, start_y);

        g.drawLine(start_x + real_width, start_y,
                start_x + real_wholeWidth, start_y + (int)(real_wholeHeight/2) );


        g.drawLine(start_x + real_width, start_y+real_wholeHeight,
                start_x + real_wholeWidth, start_y + (int)(real_wholeHeight/2) );

        g.drawLine(start_x + real_width, start_y+real_wholeHeight,
                start_x, start_y+real_wholeHeight);

        g.drawLine(start_x, start_y,
                start_x, start_y+real_wholeHeight);

        // ##4## print text on button
        g.setColor( Color.black );
        g.setFont( new java.awt.Font("Verdana", 0, 9) );
        if((statu == status.button_canbehide)||(statu == status.button_canbehide_mouse)){
            g.drawString("Hide", start_x + 8, start_y + real_wholeHeight - 6);
        }
        else
        {
            g.drawString("Diff", start_x + 8, start_y + real_wholeHeight - 6);
        }



        /*
        // draw outline
        g.setColor(out);
        g.drawRoundRect(start_x, start_y, real_width, real_height, 6, 6);

        // fill inner
        g.setColor(inner);
        g.fillRect(start_x+3, start_y+3, real_width-5, real_height-5);

        // draw inner line
        g.setColor(line);
        g.drawRoundRect(start_x+1, start_y+1, real_width-2, real_height-2, 5, 5);
        g.drawRoundRect(start_x+2, start_y+2, real_width-4, real_height-4, 4, 4);

        g.setColor( new Color(82,35,35) );
        g.setColor( Color.white );
        g.setFont( new java.awt.Font("Ayuthaya", 1, 14) );
        g.drawString("Diff >>", start_x + 8, start_y + real_height - 5);
        */



        /* 描绘一个大圆角按钮
        // ##1## draw outside round rectangle
        Color color_outline;
        if((statu == status.button_canbeExpand)||(statu == status.button_canbeExpand_mouseon)){        
            color_outline = new Color(80,14,78);
        }else
            color_outline = new Color( 51,  51,  51 );

        g.setColor( color_outline );
        g.drawRoundRect(start_x, start_y, real_width, real_height, 8, 8);

        // ##2## fill the round rectangle area
        Color color_fill = Color.white;
        if(statu == status.button_canbeExpand){
            color_fill = new Color(80,14,78);
        }else if (statu == status.button_canbeExpand_mouseon){
            color_fill = new Color(160,24,156);
        }else if(statu == status.button_canbehide){
            color_fill = new Color(128, 128, 128 );
        }else if (statu == status.button_canbehide_mouse){
            color_fill = new Color(200,200,200);
        }
        g.setColor(color_fill);
        g.fillRoundRect(start_x+1, start_y+1, real_width-2, real_height-2, 8,8);


        // ##3## draw a round rectangle with same coefficients with step3, but
        // color are white.
        g.setColor(Color.white);
        g.drawRoundRect(start_x+1, start_y+1, real_width-2, real_height-2, 8, 8);

        

        // ##4## print text on button
        g.setColor( Color.white );
        g.setFont( new java.awt.Font("Calibri", 1, 14) );
        if((statu == status.button_canbehide)||(statu == status.button_canbehide_mouse)){
            g.drawString("Hide <<", start_x + 8, start_y + real_height - 6);
        }
        else
        {
            g.drawString("Diff >>", start_x + 8, start_y + real_height - 6);
        }
         *
         */
    }
}
